package service

import (
	database "MyBlogv2/common/database"
	"MyBlogv2/common/helper"
	"MyBlogv2/common/models"
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/jmoiron/sqlx"
	ark "github.com/sashabaranov/go-openai"
)

// AIAgent 增强的AI助手，支持工具调用
type AIAgent struct {
	client         *ark.Client
	model          string
	history        []ark.ChatCompletionMessage
	maxTokens      int
	sessionID      string
	db             *sqlx.DB
	tools          []ark.Tool // 可用工具列表
	articleInfo    string
	articleContent string
}

// API请求和响应结构体
type AgentRequest struct {
	UserMessage    string `json:"user_message" binding:"required"`
	ArticleInfo    string `json:"article_info"`
	ArticleContent string `json:"article_content"`
	SessionID      string `json:"session_id"`
	Type           string `json:"type"`
	Model          string `json:"model"`
}

type SaveArticleRequest struct {
	SessionID       string `json:"session_id" binding:"required"`
	ArticleContent  string `json:"article_content" `
	ArticleTitle    string `json:"article_title" `
	ArticleCategory string `json:"article_category" `
	ArticleTags     string `json:"article_tags" `
	ArticleCover    string `json:"article_cover" `
}

type GetArticleResponse struct {
	Success         bool   `json:"success" `
	Error           string `json:"error" `
	ArticleContent  string `json:"article_content" db:"article_content" `
	ArticleTitle    string `json:"article_title" db:"article_title" `
	ArticleCategory string `json:"article_category" db:"article_category" `
	ArticleTags     string `json:"article_tags" db:"article_tags" `
	ArticleCover    string `json:"article_cover" db:"article_cover" `
}

// EditItem 批量编辑的单个项目
type EditItem struct {
	OldContent string `json:"old_content"`
	NewContent string `json:"new_content"`
}

type AgentSessionListResponse struct {
	Sessions []AgentSession `json:"sessions"`
	Success  bool           `json:"success"`
	Error    string         `json:"error,omitempty"`
}

// AgentSession 表示一个对话会话
type AgentSession struct {
	ID        string                      `json:"id"`
	Name      string                      `json:"name"`
	History   []ark.ChatCompletionMessage `json:"history"`
	CreatedAt time.Time                   `json:"created_at"`
	UpdatedAt time.Time                   `json:"updated_at"`
}

type AgentSessionResponse struct {
	Session         AgentSession `json:"session"`
	Success         bool         `json:"success"`
	ArticleContent  string       `json:"article_content"`
	ArticleTitle    string       `json:"article_title"`
	ArticleCategory string       `json:"article_category"`
	ArticleTags     string       `json:"article_tags"`
	ArticleCover    string       `json:"article_cover"`
	Error           string       `json:"error,omitempty"`
}

// SessionRow 数据库行结构体
type AgentSessionRow struct {
	SessionID       string    `db:"session_id"`
	SessionName     string    `db:"session_name"`
	Content         string    `db:"content"`
	UserID          int       `db:"user_id"`
	ArticleContent  string    `db:"article_content"`
	ArticleTitle    string    `db:"article_title"`
	ArticleCategory string    `db:"article_category"`
	ArticleTags     string    `db:"article_tags"`
	ArticleCover    string    `db:"article_cover"`
	CreatedAt       time.Time `db:"created_at"`
	UpdatedAt       time.Time `db:"updated_at"`
}

// AgentSessionModel GORM模型
type AgentSessionModel struct {
	SessionID       string    `gorm:"column:session_id;primaryKey"`
	SessionName     string    `gorm:"column:session_name"`
	Content         string    `gorm:"column:content"`
	ArticleContent  string    `gorm:"column:article_content"`
	ArticleTitle    string    `gorm:"column:article_title"`
	ArticleCategory string    `gorm:"column:article_category"`
	ArticleTags     string    `gorm:"column:article_tags"`
	ArticleCover    string    `gorm:"column:article_cover"`
	CreatedAt       time.Time `gorm:"column:created_at"`
	UpdatedAt       time.Time `gorm:"column:updated_at"`
}

func (AgentSessionModel) TableName() string {
	return "agent_sessions"
}

// 自定义Transport类型定义
type userAgentTransport struct {
	http.RoundTripper
	userAgent string
}

func (t *userAgentTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	req.Header.Set("User-Agent", t.userAgent)
	return t.RoundTripper.RoundTrip(req)
}

// NewAIChatWithSession 创建AIAgent实例，可选择指定sessionID
func NewAIAgentWithSession(apiKey, baseURL, model string, sessionID string) *AIAgent {
	// // 配置本地代理
	// proxyURL, err := url.Parse("http://127.0.0.1:7897") // 请根据您的代理端口修改
	// if err != nil {
	// 	fmt.Printf("代理URL解析错误: %v\n", err)
	// 	return nil
	// }

	// // 创建HTTP传输器并设置代理
	// transport := &http.Transport{
	// 	Proxy: http.ProxyURL(proxyURL),
	// }

	// // 包装transport添加User-Agent
	// customTransport := &userAgentTransport{
	// 	RoundTripper: transport,
	// 	userAgent:    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
	// }

	// // 创建HTTP客户端
	// httpClient := &http.Client{
	// 	Transport: customTransport,
	// }
	config := ark.DefaultConfig(apiKey)
	config.BaseURL = baseURL
	// config.HTTPClient = httpClient
	client := ark.NewClientWithConfig(config)

	// 初始化系统消息，包含工具使用说明
	// systemMessage := ``

	history := []ark.ChatCompletionMessage{}

	tools := []ark.Tool{
		{
			Type: ark.ToolTypeFunction,
			Function: &ark.FunctionDefinition{
				Name:        "update_title",
				Description: "更新文章标题",
				Parameters: map[string]interface{}{
					"type": "object",
					"properties": map[string]interface{}{
						"new_title": map[string]interface{}{
							"type":        "string",
							"description": "修改后的标题",
						},
						"summary": map[string]interface{}{
							"type":        "string",
							"description": "简短描述这次修改（不超过15字）",
						},
					},
					"required": []string{"new_title", "summary"},
				},
			},
		},
		{
			Type: ark.ToolTypeFunction,
			Function: &ark.FunctionDefinition{
				Name:        "update_category",
				Description: "更新文章分类",
				Parameters: map[string]interface{}{
					"type": "object",
					"properties": map[string]interface{}{
						"new_category": map[string]interface{}{
							"type":        "string",
							"description": "修改后的分类",
						},
						"summary": map[string]interface{}{
							"type":        "string",
							"description": "简短描述这次修改（不超过15字）",
						},
					},
					"required": []string{"new_category", "summary"},
				},
			},
		},
		// {
		// 	Type: ark.ToolTypeFunction,
		// 	Function: &ark.FunctionDefinition{
		// 		Name:        "update_tags",
		// 		Description: "更新文章标签",
		// 		Parameters: map[string]interface{}{
		// 			"type": "object",
		// 			"properties": map[string]interface{}{
		// 				"new_tags": map[string]interface{}{
		// 					"type":        "array",
		// 					"items":       map[string]interface{}{"type": "string"},
		// 					"description": "修改后的标签数组",
		// 				},
		// 				"summary": map[string]interface{}{
		// 					"type":        "string",
		// 					"description": "简短描述这次修改（不超过15字）",
		// 				},
		// 			},
		// 			"required": []string{"new_tags", "summary"},
		// 		},
		// 	},
		// },
		{
			Type: ark.ToolTypeFunction,
			Function: &ark.FunctionDefinition{
				Name: "read_article",
				Description: `读取完整的文章内容。在编辑文章前，应先调用此工具了解当前内容。`,
				Parameters: map[string]interface{}{
					"type":       "object",
					"properties": map[string]interface{}{},
				},
			},
		},
		{
			Type: ark.ToolTypeFunction,
			Function: &ark.FunctionDefinition{
				Name: "get_categories",
				Description: `获取所有可用的文章分类列表。在更新分类前，应先调用此工具查看可选项。`,
				Parameters: map[string]interface{}{
					"type":       "object",
					"properties": map[string]interface{}{},
				},
			},
		},
		// {
		// 	Type: ark.ToolTypeFunction,
		// 	Function: &ark.FunctionDefinition{
		// 		Name: "get_tags",
		// 		Description: `获取所有可用的文章标签列表。在更新标签前，应先调用此工具查看可选项。`,
		// 		Parameters: map[string]interface{}{
		// 			"type":       "object",
		// 			"properties": map[string]interface{}{},
		// 		},
		// 	},
		// },
		{
			Type: ark.ToolTypeFunction,
			Function: &ark.FunctionDefinition{
				Name: "edit_article",
				Description: `基于内容精确匹配编辑文章。使用此工具修改或替换文章中的特定内容。

重要规则：
1. old_content 必须在文章中精确存在且唯一
2. 如果不确定内容，先调用 read_article 查看
3. 包含足够的上下文（前后文）确保 old_content 唯一性
4. 支持多行内容的替换
5. 不要向用户提及工具名称，直接说"我已经..."

示例：
- 修改段落：old_content 应包含完整段落
- 修改标题：old_content 应包含标题及其前后内容
- 插入内容：old_content 设为插入位置的前一段内容，new_content 包含原内容+新内容`,
				Parameters: map[string]interface{}{
					"type": "object",
					"properties": map[string]interface{}{
						"old_content": map[string]interface{}{
							"type":        "string",
							"description": "要替换的原始内容，必须精确匹配且唯一",
						},
						"new_content": map[string]interface{}{
							"type":        "string",
							"description": "新内容",
						},
						"summary": map[string]interface{}{
							"type":        "string",
							"description": "简短描述这次修改（不超过15字）",
						},
					},
					"required": []string{"old_content", "new_content", "summary"},
				},
			},
		},
		{
			Type: ark.ToolTypeFunction,
			Function: &ark.FunctionDefinition{
				Name: "edit_article_batch",
				Description: `批量编辑文章的多个位置。当需要修改两处或以上时，应使用此工具而不是多次调用 edit_article。
				
重要规则：
1. 每个 old_content 都必须在文章中精确存在且唯一
2. 批量操作是原子性的：要么全部成功，要么全部失败
3. 如果某个 old_content 不唯一或不存在，整个操作会失败
4. 不要向用户提及工具名称

适用场景：
- 修改多个段落
- 在多个位置插入内容
- 统一修改多处相似内容`,
				Parameters: map[string]interface{}{
					"type": "object",
					"properties": map[string]interface{}{
						"edits": map[string]interface{}{
							"type": "array",
							"items": map[string]interface{}{
								"type": "object",
								"properties": map[string]interface{}{
									"old_content": map[string]interface{}{
										"type":        "string",
										"description": "要替换的原始内容，必须唯一",
									},
									"new_content": map[string]interface{}{
										"type":        "string",
										"description": "新内容",
									},
								},
								"required": []string{"old_content", "new_content"},
							},
							"description": "批量编辑的数组",
						},
						"summary": map[string]interface{}{
							"type":        "string",
							"description": "简短描述这批修改（不超过15字）",
						},
					},
					"required": []string{"edits", "summary"},
				},
			},
		},
	}

	// 如果没有提供sessionID，生成一个新的
	if sessionID == "" {
		sessionID = generateSessionID()
	}

	return &AIAgent{
		client:    client,
		model:     model,
		history:   history,
		maxTokens: 5000,
		sessionID: sessionID,
		db:        database.Db,
		tools:     tools,
	}
}

// AgentChat 支持工具调用的AIAgent聊天接口
func AgentChat(c *gin.Context) {
	// 获取用户ID
	userIDInterface, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, ChatResponse{
			Success: false,
			Error:   "未登录",
		})
		return
	}
	userID := userIDInterface.(int)

	var req AgentRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, ChatResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}

	// 创建AI Agent实例，如果提供了sessionID则使用它
	agent := NewAIAgentWithSession(
		agent_config["content"][req.Model]["api_key"],
		agent_config["content"][req.Model]["base_url"],
		agent_config["content"][req.Model]["model"],
		req.SessionID, // 直接传入sessionID，如果为空则生成新的
	)

	agent.articleInfo = req.ArticleInfo
	agent.articleContent = req.ArticleContent
	// 如果提供了sessionID，尝试加载该会话
	if req.SessionID != "" {
		if err := agent.LoadAgentSession(req.SessionID, userID); err != nil {
			// 如果加载失败，使用新生成的sessionID
			fmt.Printf("加载会话失败，使用新会话: %v\n", err)
		}
	}

	// 流式响应
	c.Header("Content-Type", "text/event-stream; charset=utf-8")
	c.Header("Cache-Control", "no-cache")
	c.Header("Connection", "keep-alive")
	c.Header("Access-Control-Allow-Origin", "*")
	c.Header("Access-Control-Allow-Headers", "Content-Type")
	c.Header("Access-Control-Allow-Methods", "POST, OPTIONS")

	// 使用Agent进行真实流式聊天（支持工具调用和思考过程）
	if err := agent.ChatWithToolsStreamReal(req.UserMessage, req.ArticleInfo, req.ArticleContent, c.Writer); err != nil {
		c.JSON(http.StatusInternalServerError, ChatResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}

	// 自动保存会话
	if err := agent.SaveSession(userID); err != nil {
		fmt.Printf("警告: 自动保存会话失败: %v\n", err)
	}

	// 发送结束信号
	endData := fmt.Sprintf(`{"type":"end","session_id":"%s"}`, agent.sessionID)
	c.Writer.WriteString(fmt.Sprintf("data: %s\n\n", endData))
	c.Writer.WriteString("data: [DONE]\n\n")
	c.Writer.Flush()
}

func GetTags() []string {
	var tagList []string
	models.Db.Model(new(models.Tag)).Pluck("tag_name", &tagList)
	return tagList
}

func GetCategories() []string {
	var categoryList []string
	models.Db.Model(new(models.Category)).Pluck("category_name", &categoryList)
	return categoryList
}

// ChatWithToolsStreamReal 真正的流式聊天，支持工具调用和思考过程展示
func (agent *AIAgent) ChatWithToolsStreamReal(userMessage string, articleInfo string, articleContent string, writer gin.ResponseWriter) error {
	agent.history = append(agent.history, ark.ChatCompletionMessage{
		Role: ark.ChatMessageRoleSystem,
		Content: `You are an expert article editor AI with specialized tools for writing, editing, and publishing Markdown articles.

# Chain of Thought Reasoning

Before executing any task, you MUST follow this thinking process:

1. **Understand the Request**: Clearly identify what the user is asking for
2. **Plan Your Approach**: Break down the task into logical steps
3. **Identify Required Tools**: Determine which tools you need to use and in what order
4. **Anticipate Challenges**: Consider potential issues (content matching, uniqueness, etc.)
5. **Execute Step-by-Step**: Follow your plan, adjusting as needed based on results

**Example Reasoning Pattern:**
User: "Update the introduction and change category to Tech"

Your thinking:
- Task: Two operations - content edit + metadata update
- Steps needed:
  1. Verify "Tech" category exists (get_categories)
  2. Read current article to locate introduction (read_article)
  3. Edit the introduction content (edit_article)
  4. Update category (update_category)
- Potential issues: Introduction might not be clearly marked, need unique content match
- Execution: Start with parallel reads, then sequential edits

**Always think through your approach before taking action**, but execute confidently once you have a plan.

---

# Core Principles

1. **Always verify before editing**: Call read_article to understand current content
2. **Precise content matching**: old_content must match exactly and be unique
3. **Execute confidently**: Make changes directly without asking permission
4. **Communicate clearly**: Describe what you changed, not how you did it
5. **Verify your work**: Check results after making changes

---

# Available Tools

## Query Tools
- **get_categories**: List all available article categories
- **read_article**: Read current article content

## Metadata Tools
- **update_title**: Update article title
- **update_category**: Update article category (verify existence with get_categories first)

## Content Editing Tools
- **edit_article**: Edit a single location using content matching
- **edit_article_batch**: Edit multiple locations atomically (all-or-nothing)

---

# Tool Usage Guide

## 1. get_categories

**When to use:**
- Before calling update_category
- When user asks "what categories are available?"

**Example:**
User: "Change category to Tech"
→ Call get_categories first to verify "Tech" exists
→ Then call update_category("Tech")

## 2. read_article

**When to use:**
- ALWAYS before any content edit
- When user asks to view/check content
- After making edits to verify results

**Example workflow:**
User: "Fix the typo in the introduction"
→ Call read_article to see current content
→ Locate the typo
→ Call edit_article to fix it

## 3. edit_article

**Critical requirements:**
- old_content MUST match exactly (case-sensitive, whitespace-sensitive)
- old_content MUST be unique in the article
- Include enough context to ensure uniqueness

**DO:**
✓ Include surrounding sentences for context
✓ Match exact punctuation and formatting
✓ Use multi-line old_content for paragraphs

**DON'T:**
✗ Use partial words or phrases that appear multiple times
✗ Guess at content - always read first
✗ Modify content without sufficient context

**Example 1: Modify a heading**
Article contains:
"""
## Introduction
Vue.js is a progressive framework.
"""

CORRECT:
old_content: "## Introduction\nVue.js is a progressive framework."
new_content: "## Getting Started\nVue.js is a progressive framework."

INCORRECT (not unique):
old_content: "Introduction"  // ❌ Might appear elsewhere
old_content: "##"  // ❌ Too vague

**Example 2: Modify a paragraph**
Article contains:
"""
The framework offers excellent performance. It uses a virtual DOM for efficient updates. This makes it fast.
"""

User: "Expand on why it's fast"

CORRECT:
old_content: "It uses a virtual DOM for efficient updates. This makes it fast."
new_content: "It uses a virtual DOM for efficient updates, which minimizes actual DOM manipulations. This intelligent diffing algorithm makes it extremely fast."

**Example 3: Insert content**
Article contains:
"""
## Features
- Reactive data binding

## Installation
Run npm install
"""

User: "Add component-based architecture to features"

CORRECT:
old_content: "## Features\n- Reactive data binding\n\n## Installation"
new_content: "## Features\n- Reactive data binding\n- Component-based architecture\n\n## Installation"

## 4. edit_article_batch

**When to use:**
- Multiple related changes needed
- Changes in different locations
- Atomic operation required (all succeed or all fail)

**Example:**
User: "Update all examples to use TypeScript syntax"

edits: [
  {
    old_content: "const app = createApp({",
    new_content: "const app: App = createApp({"
  },
  {
    old_content: "const message = ref('hello')",
    new_content: "const message = ref<string>('hello')"
  }
]

---

# Workflow Patterns

## Pattern 1: Simple Content Edit
User: "Fix the typo 'framwork' to 'framework'"
1. read_article → locate "framwork"
2. edit_article with context around the typo
3. Respond: "Fixed the typo - changed 'framwork' to 'framework'"

## Pattern 2: Metadata Update
User: "Change category to Tech"
1. get_categories → verify "Tech" exists
2. update_category("Tech")
3. Respond: "Updated category to Tech"

## Pattern 3: Complex Content Restructure
User: "Reorganize the article - move the conclusion before the summary"
1. read_article → understand structure
2. edit_article_batch with multiple moves
3. read_article → verify structure
4. Respond: "Reorganized the article - moved conclusion before summary"

## Pattern 4: Error Recovery
1. edit_article fails with "content not found"
2. read_article → see what actually exists
3. Identify the discrepancy
4. edit_article again with correct old_content
5. Respond with what you fixed

---

# Response Guidelines

## Communication Style

**DO:**
- Use natural language: "I've updated the introduction to..."
- Be specific: "Changed 'Vue 2' to 'Vue 3' in all code examples"
- Acknowledge completion: "Done! The article now uses TypeScript syntax"

**DON'T:**
- Mention tool names: ❌ "I called edit_article..."
- Ask for permission: ❌ "Should I update this section?"
- Repeat entire content: ❌ "The new article is: [3000 words]..."
- Over-explain process: ❌ "First I'll read, then match content, then..."

## Examples

User: "Make the code examples more readable"
✓ Good: "I've reformatted the code examples with better indentation and added comments"
✗ Bad: "I used edit_article_batch to modify code blocks..."

User: "Improve the introduction"  
✓ Good: "I've enhanced the introduction to be more engaging and added context about why this topic matters"
✗ Bad: "Should I make it more engaging? What specific improvements do you want?"

---

# Error Handling

## "Content not found" Error

**Cause:** old_content doesn't exist in article

**Action:**
1. Call read_article to see current state
2. Find what the content actually is
3. Retry with correct old_content

**Response to user:**
"I see the content has changed - let me update based on the current version"

## "Multiple matches found" Error

**Cause:** old_content appears more than once

**Action:**
1. Add more context before/after to make it unique
2. Include adjacent paragraphs or headings

**Example:**
Instead of:
old_content: "Vue.js is great"  // ❌ Appears 3 times

Use:
old_content: "## Why Choose Vue\n\nVue.js is great for building SPAs"  // ✓ Unique

## Invalid Category Error

**Cause:** Category doesn't exist in system

**Action:**
1. Call get_categories to see available options
2. Suggest valid alternatives to user

**Response to user:**
"The category 'JavaScript' isn't available. Current categories are: Tech, Tutorial, Blog. Which would you prefer?"

---

# Edge Cases

## Empty Article
If read_article returns "(文章内容为空)":
- Inform user article is empty
- Offer to help write initial content
- Ask what topic or outline they want

## User Asks to Delete Content
Use edit_article with new_content as empty or remove the section:
old_content: "## Old Section\nContent to remove\n\n"
new_content: ""

## Multiple Similar Sections
If article has repeated structures (e.g., multiple "## Example"):
- Include unique parent heading in old_content
- Use content from the specific section needed

---

# Best Practices

1. **Read first, act second**: Always call read_article before editing
2. **Context is key**: Include 2-3 lines of context around the target
3. **Verify results**: After major edits, read_article again to confirm
4. **Atomic batches**: Group related changes in edit_article_batch
5. **Clear communication**: Tell user what changed, not how you did it
6. **Handle errors gracefully**: If tools fail, adapt and retry
7. **Validate metadata**: Always check categories exist before updating

---

# Output Format

All article content MUST be valid Markdown`,
	})

	agent.history = append(agent.history, ark.ChatCompletionMessage{
		Role:    ark.ChatMessageRoleUser,
		Content: "<article_info>\n" + articleInfo + "\n</article_info>",
	})

	agent.history = append(agent.history, ark.ChatCompletionMessage{
		Role:    ark.ChatMessageRoleUser,
		Content: "<article_content>\n" + articleContent + "\n</article_content>",
	})

	fmt.Println("<article_content>\n" + articleContent + "\n</article_content>")

	// agent.history = append(agent.history, ark.ChatCompletionMessage{
	// 	Role: ark.ChatMessageRoleUser,
	// 	Content: "<category_and_tag>\n" + "可选的分类和标签:\n分类: " + strings.Join(GetCategories(), ", ") +
	// 		"\n标签: " + strings.Join(GetTags(), ", ") + "\n</category_and_tag>",
	// })
	// 添加用户消息
	agent.history = append(agent.history, ark.ChatCompletionMessage{
		Role:    ark.ChatMessageRoleUser,
		Content: userMessage,
	})

	ctx := context.Background()
	maxIterations := 10 // 防止无限循环
	iteration := 0

	for iteration < maxIterations {
		iteration++

		// 创建流式聊天完成请求，包含工具
		req := ark.ChatCompletionRequest{
			Model:    agent.model,
			Messages: agent.history,
			Tools:    agent.tools,
			Stream:   true, // 开启流式模式
		}
		fmt.Println(req.Messages)
		// 创建流式请求
		stream, err := agent.client.CreateChatCompletionStream(ctx, req)
		if err != nil {
			fmt.Println(err)
			return fmt.Errorf("AI流式请求失败: %v", err)
		}

		var fullContent strings.Builder
		var fullReasoning strings.Builder
		var toolCalls []ark.ToolCall
		var currentBubbleID string
		var thinkingBubbleID string
		var thinkingStarted bool
		toolBubbleIDs := make(map[int]string) // 存储每个工具调用的bubble_id

		// 接收流式响应
		for {
			response, err := stream.Recv()
			if err == io.EOF {
				break
			}
			if err != nil {
				stream.Close()
				return fmt.Errorf("接收流式响应失败: %v", err)
			}

			if len(response.Choices) == 0 {
				continue
			}

			delta := response.Choices[0].Delta

			// 处理 thinking/reasoning 内容（必须在普通内容之前）
			if delta.ReasoningContent != "" {
				fullReasoning.WriteString(delta.ReasoningContent)

				// 发送 thinking_start 信号（仅首次）
				if !thinkingStarted {
					thinkingBubbleID = fmt.Sprintf("thinking_%d", time.Now().UnixNano())
					thinkingStartData := map[string]interface{}{
						"type":       "thinking_start",
						"session_id": agent.sessionID,
						"bubble_id":  thinkingBubbleID,
					}
					jsonData, _ := json.Marshal(thinkingStartData)
					writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
					writer.Flush()
					thinkingStarted = true
				}

				// 流式输出 thinking 内容
				thinkingData := map[string]interface{}{
					"type":       "thinking",
					"content":    delta.ReasoningContent,
					"session_id": agent.sessionID,
					"bubble_id":  thinkingBubbleID,
				}
				jsonData, _ := json.Marshal(thinkingData)
				writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
				writer.Flush()
			}

			// 处理内容流式输出
			if delta.Content != "" {
				// 如果之前有 thinking，先发送 thinking_end
				if thinkingStarted && thinkingBubbleID != "" {
					thinkingEndData := map[string]interface{}{
						"type":       "thinking_end",
						"session_id": agent.sessionID,
						"bubble_id":  thinkingBubbleID,
					}
					jsonData, _ := json.Marshal(thinkingEndData)
					writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
					writer.Flush()
					thinkingBubbleID = "" // 重置，避免重复发送
					thinkingStarted = false
				}

				// 普通内容
				fullContent.WriteString(delta.Content)

				if currentBubbleID == "" {
					currentBubbleID = fmt.Sprintf("response_%d", time.Now().UnixNano())
				}

				contentData := map[string]interface{}{
					"type":       "content",
					"content":    delta.Content,
					"session_id": agent.sessionID,
					"bubble_id":  currentBubbleID,
				}
				jsonData, _ := json.Marshal(contentData)
				writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
				writer.Flush()
			}

			// 处理工具调用（流式模式下逐步累积）
			if len(delta.ToolCalls) > 0 {
				// 如果之前有 thinking，先发送 thinking_end
				if thinkingStarted && thinkingBubbleID != "" {
					thinkingEndData := map[string]interface{}{
						"type":       "thinking_end",
						"session_id": agent.sessionID,
						"bubble_id":  thinkingBubbleID,
					}
					jsonData, _ := json.Marshal(thinkingEndData)
					writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
					writer.Flush()
					thinkingBubbleID = "" // 重置，避免重复发送
					thinkingStarted = false
				}

				for _, toolCallDelta := range delta.ToolCalls {
					// 查找或创建对应的工具调用
					index := *toolCallDelta.Index

					// 扩展toolCalls数组
					for len(toolCalls) <= index {
						toolCalls = append(toolCalls, ark.ToolCall{})
					}

					// 累积工具调用信息
					if toolCallDelta.ID != "" {
						toolCalls[index].ID = toolCallDelta.ID
					}
					if toolCallDelta.Type != "" {
						toolCalls[index].Type = toolCallDelta.Type
					}
					if toolCallDelta.Function.Name != "" {
						toolCalls[index].Function.Name = toolCallDelta.Function.Name

						// 为该工具调用生成唯一的bubble_id
						if _, exists := toolBubbleIDs[index]; !exists {
							toolBubbleIDs[index] = fmt.Sprintf("tool_%s_%d", toolCallDelta.Function.Name, time.Now().UnixNano())
						}

						// 发送工具调用开始信号
						toolStartData := map[string]interface{}{
							"type":       "tool_start",
							"tool_name":  toolCallDelta.Function.Name,
							"session_id": agent.sessionID,
							"bubble_id":  toolBubbleIDs[index],
						}
						jsonData, _ := json.Marshal(toolStartData)
						writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
						writer.Flush()
					}
					if toolCallDelta.Function.Arguments != "" {
						toolCalls[index].Function.Arguments += toolCallDelta.Function.Arguments
					}
				}
			}
		}

		stream.Close()

		// 如果 thinking 结束了但还没发送 thinking_end（比如流结束时）
		if thinkingStarted && thinkingBubbleID != "" {
			thinkingEndData := map[string]interface{}{
				"type":       "thinking_end",
				"session_id": agent.sessionID,
				"bubble_id":  thinkingBubbleID,
			}
			jsonData, _ := json.Marshal(thinkingEndData)
			writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
			writer.Flush()
		}

		assistantMessage := ark.ChatCompletionMessage{
			Role:             ark.ChatMessageRoleAssistant,
			ReasoningContent: fullReasoning.String(),
			Content:          fullContent.String(),
		}

		// 如果有工具调用
		if len(toolCalls) > 0 {
			assistantMessage.ToolCalls = toolCalls
			agent.history = append(agent.history, assistantMessage)

			// 执行所有工具调用
			for index, toolCall := range toolCalls {
				// 获取该工具调用的bubble_id
				bubbleID := toolBubbleIDs[index]

				// 执行工具
				toolResult, err := agent.ExecuteTool(toolCall)
				if err != nil {
					toolResult = fmt.Sprintf("工具执行失败: %v", err)
				}

				// 流式输出工具结果
				agent.streamToolResult(toolResult, writer, bubbleID, toolCall.Function.Name)

				// 修复空 content 问题：tool 消息的 content 不能为空
				if toolResult == "" {
					toolResult = " " // 使用空格作为占位符
				}

				// 添加工具结果到历史
				agent.history = append(agent.history, ark.ChatCompletionMessage{
					Role:       ark.ChatMessageRoleTool,
					Content:    toolResult,
					ToolCallID: toolCall.ID,
					Name:       toolCall.Function.Name,
				})

				// 发送工具调用结束信号
				toolEndData := map[string]interface{}{
					"type":        "tool_end",
					"tool_name":   toolCall.Function.Name,
					"session_id":  agent.sessionID,
					"bubble_id":   bubbleID,
					"tool_result": "Success",
				}
				jsonData, _ := json.Marshal(toolEndData)
				writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
				writer.Flush()
			}

			// 继续下一轮迭代
			continue
		} else {
			// 没有工具调用，添加消息到历史并结束
			agent.history = append(agent.history, assistantMessage)
			break
		}
	}

	if iteration >= maxIterations {
		errorData := map[string]interface{}{
			"type":    "error",
			"content": "达到最大迭代次数，对话终止",
		}
		jsonData, _ := json.Marshal(errorData)
		writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
		writer.Flush()
	}

	agent.history = clearSystemMessage(agent.history)
	return nil
}

func clearSystemMessage(history []ark.ChatCompletionMessage) []ark.ChatCompletionMessage {
	j := 0
	for _, msg := range history {
		// 跳过系统消息
		if msg.Role == ark.ChatMessageRoleSystem {
			continue
		}

		// 跳过特定的用户消息（文章信息、内容和分类标签）
		if msg.Role == ark.ChatMessageRoleUser {
			content := msg.Content
			if strings.HasPrefix(content, "<article_info>") ||
				strings.HasPrefix(content, "<article_content>") ||
				strings.HasPrefix(content, "<category_and_tag>") {
				continue
			}
		}

		history[j] = msg
		j++
	}
	return history[:j]
}

// ExecuteTool 执行工具调用
func (agent *AIAgent) ExecuteTool(toolCall ark.ToolCall) (string, error) {
	if toolCall.Function.Name == "" {
		return "", fmt.Errorf("工具调用缺少函数信息")
	}

	functionName := toolCall.Function.Name
	arguments := toolCall.Function.Arguments

	// 解析参数
	var params map[string]interface{}
	if err := json.Unmarshal([]byte(arguments), &params); err != nil {
		return "", fmt.Errorf("解析工具参数失败: %v", err)
	}
	fmt.Println("params:", params)

	switch functionName {
	case "update_title":
		newTitle, _ := params["new_title"].(string)
		summary, _ := params["summary"].(string)
		return agent.UpdateTitle(newTitle, summary)
	case "update_category":
		newCategory, _ := params["new_category"].(string)
		summary, _ := params["summary"].(string)
		return agent.UpdateCategory(newCategory, summary)
	case "update_tags":
		var tagList []string
		if raw, ok := params["new_tags"]; ok && raw != nil {
			if arr, ok2 := raw.([]interface{}); ok2 {
				for _, v := range arr {
					if s, ok3 := v.(string); ok3 {
						tagList = append(tagList, s)
					}
				}
			}
		}
		summary, _ := params["summary"].(string)
		return agent.UpdateTags(tagList, summary)
	case "read_article":
		return agent.ReadArticle()
	case "get_categories":
		return agent.GetCategoriesList()
	case "get_tags":
		return agent.GetTagsList()
	case "edit_article":
		oldContent, _ := params["old_content"].(string)
		newContent, _ := params["new_content"].(string)
		summary, _ := params["summary"].(string)
		return agent.EditArticle(oldContent, newContent, summary)
	case "edit_article_batch":
		var edits []EditItem
		if raw, ok := params["edits"]; ok && raw != nil {
			if arr, ok2 := raw.([]interface{}); ok2 {
				for _, v := range arr {
					if editMap, ok3 := v.(map[string]interface{}); ok3 {
						oldContent, _ := editMap["old_content"].(string)
						newContent, _ := editMap["new_content"].(string)
						edits = append(edits, EditItem{
							OldContent: oldContent,
							NewContent: newContent,
						})
					}
				}
			}
		}
		summary, _ := params["summary"].(string)
		return agent.EditArticleBatch(edits, summary)

	default:
		return "", fmt.Errorf("未知的工具函数: %s", functionName)
	}
}

func (agent *AIAgent) UpdateTitle(newTitle string, summary string) (string, error) {
	respMap := map[string]interface{}{
		"success":     true,
		"new_title":   newTitle,
		"summary": summary,
	}
	jsonData, err := json.Marshal(respMap)
	if err != nil {
		return "", fmt.Errorf("JSON序列化失败: %v", err)
	}
	return string(jsonData), nil
}

func (agent *AIAgent) UpdateCategory(newCategory string, summary string) (string, error) {
	// 验证分类是否存在
	availableCategories := GetCategories()
	found := false
	for _, cat := range availableCategories {
		if cat == newCategory {
			found = true
			break
		}
	}
	
	if !found {
		return "", fmt.Errorf("分类 '%s' 不存在。请先调用 get_categories 工具查看所有可用分类", 
			newCategory)
	}
	
	respMap := map[string]interface{}{
		"success":      true,
		"new_category": newCategory,
		"summary":      summary,
	}
	jsonData, err := json.Marshal(respMap)
	if err != nil {
		return "", fmt.Errorf("JSON序列化失败: %v", err)
	}
	return string(jsonData), nil
}

func (agent *AIAgent) UpdateTags(newTags []string, summary string) (string, error) {
	// 验证所有标签是否存在
	availableTags := GetTags()
	tagSet := make(map[string]bool)
	for _, tag := range availableTags {
		tagSet[tag] = true
	}
	
	var invalidTags []string
	for _, tag := range newTags {
		if !tagSet[tag] {
			invalidTags = append(invalidTags, tag)
		}
	}
	
	if len(invalidTags) > 0 {
		return "", fmt.Errorf("标签 %s 不存在。请先调用 get_tags 工具查看所有可用标签", 
			strings.Join(invalidTags, ", "))
	}
	
	respMap := map[string]interface{}{
		"success":  true,
		"new_tags": newTags,
		"summary":  summary,
	}
	jsonData, err := json.Marshal(respMap)
	if err != nil {
		return "", fmt.Errorf("JSON序列化失败: %v", err)
	}
	return string(jsonData), nil
}

// GetCategoriesList 获取所有可用的分类列表
func (agent *AIAgent) GetCategoriesList() (string, error) {
	categories := GetCategories()
	if len(categories) == 0 {
		return "暂无可用分类", nil
	}
	return "可用的分类有：\n- " + strings.Join(categories, "\n- "), nil
}

// GetTagsList 获取所有可用的标签列表
func (agent *AIAgent) GetTagsList() (string, error) {
	tags := GetTags()
	if len(tags) == 0 {
		return "暂无可用标签", nil
	}
	return "可用的标签有：\n- " + strings.Join(tags, "\n- "), nil
}

// ReadArticle 读取文章内容
func (agent *AIAgent) ReadArticle() (string, error) {
	// 如果文章内容为空，返回明确的提示信息
	if agent.articleContent == "" {
		return "(文章内容为空)", nil
	}
	return agent.articleContent, nil
}

// EditArticle 基于内容匹配编辑文章
func (agent *AIAgent) EditArticle(oldContent, newContent, summary string) (string, error) {
	// 1. 验证 old_content 存在且唯一
	count := strings.Count(agent.articleContent, oldContent)
	if count == 0 {
		return "", fmt.Errorf("找不到要替换的内容。请先调用 read_article 查看当前内容。")
	}
	if count > 1 {
		return "", fmt.Errorf("找到 %d 处匹配。请提供更多上下文使 old_content 唯一。", count)
	}

	// 2. 执行替换
	agent.articleContent = strings.Replace(agent.articleContent, oldContent, newContent, 1)

	// 3. 返回成功信息（包含更新后的内容用于前端diff显示）
	respMap := map[string]interface{}{
		"success":         true,
		"summary":     summary,
		"updated_content": agent.articleContent,
	}
	jsonData, err := json.Marshal(respMap)
	if err != nil {
		return "", fmt.Errorf("JSON序列化失败: %v", err)
	}
	return string(jsonData), nil
}

// EditArticleBatch 批量编辑文章
func (agent *AIAgent) EditArticleBatch(edits []EditItem, summary string) (string, error) {
	// 1. 验证所有 old_content
	for i, edit := range edits {
		count := strings.Count(agent.articleContent, edit.OldContent)
		if count == 0 {
			return "", fmt.Errorf("编辑 #%d: 找不到内容", i+1)
		}
		if count > 1 {
			return "", fmt.Errorf("编辑 #%d: 找到 %d 处匹配，请提供更多上下文", i+1, count)
		}
	}

	// 2. 执行所有替换
	content := agent.articleContent
	for _, edit := range edits {
		content = strings.Replace(content, edit.OldContent, edit.NewContent, 1)
	}

	agent.articleContent = content

	// 3. 返回成功信息（包含更新后的内容用于前端diff显示）
	respMap := map[string]interface{}{
		"success":         true,
		"count":           len(edits),
		"summary":     summary,
		"updated_content": agent.articleContent,
	}
	jsonData, err := json.Marshal(respMap)
	if err != nil {
		return "", fmt.Errorf("JSON序列化失败: %v", err)
	}
	return string(jsonData), nil
}

// streamContent 流式输出内容
func (agent *AIAgent) streamContent(content string, writer gin.ResponseWriter, bubbleID string) {
	chunkSize := 20
	runes := []rune(content)

	for i := 0; i < len(runes); i += chunkSize {
		end := i + chunkSize
		if end > len(runes) {
			end = len(runes)
		}

		chunk := string(runes[i:end])

		chunkData := map[string]interface{}{
			"type":       "content",
			"content":    chunk,
			"session_id": agent.sessionID,
			"bubble_id":  bubbleID,
		}

		jsonData, err := json.Marshal(chunkData)
		if err != nil {
			// 如果JSON序列化失败，使用简单的转义
			escapedContent := strings.ReplaceAll(chunk, `\`, `\\`)
			escapedContent = strings.ReplaceAll(escapedContent, `"`, `\"`)
			escapedContent = strings.ReplaceAll(escapedContent, "\n", `\n`)
			escapedContent = strings.ReplaceAll(escapedContent, "\r", `\r`)
			escapedContent = strings.ReplaceAll(escapedContent, "\t", `\t`)
			jsonData = []byte(fmt.Sprintf(`{"type":"content","content":"%s","session_id":"%s","bubble_id":"%s"}`, escapedContent, agent.sessionID, bubbleID))
		}

		writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
		writer.Flush()

		// 添加小延迟以模拟流式效果
		time.Sleep(50 * time.Millisecond)
	}
}

// streamToolResult 流式输出工具结果
func (agent *AIAgent) streamToolResult(result string, writer gin.ResponseWriter, bubbleID string, functionName string) {
	chunkSize := 30 // 工具结果可以稍微大一些
	runes := []rune(result)

	for i := 0; i < len(runes); i += chunkSize {
		end := i + chunkSize
		if end > len(runes) {
			end = len(runes)
		}

		chunk := string(runes[i:end])

		toolResultData := map[string]interface{}{
			"type":       "tool_result",
			"content":    chunk,
			"session_id": agent.sessionID,
			"bubble_id":  bubbleID,
			"name":       functionName,
		}

		jsonData, err := json.Marshal(toolResultData)
		if err != nil {
			// 如果JSON序列化失败，使用简单的转义
			escapedContent := strings.ReplaceAll(chunk, `\`, `\\`)
			escapedContent = strings.ReplaceAll(escapedContent, `"`, `\"`)
			escapedContent = strings.ReplaceAll(escapedContent, "\n", `\n`)
			escapedContent = strings.ReplaceAll(escapedContent, "\r", `\r`)
			escapedContent = strings.ReplaceAll(escapedContent, "\t", `\t`)
			jsonData = []byte(fmt.Sprintf(`{"type":"tool_result","content":"%s","session_id":"%s","bubble_id":"%s","name":"%s"}`, escapedContent, agent.sessionID, bubbleID, toolResultData["name"]))
		}

		writer.WriteString(fmt.Sprintf("data: %s\n\n", string(jsonData)))
		writer.Flush()

		// 添加小延迟以模拟流式效果
		time.Sleep(30 * time.Millisecond)
	}
}

// LoadSession 加载会话（需要传入userID进行权限验证）
func (agent *AIAgent) LoadAgentSession(sessionID string, userID int) error {
	var contentJSON string
	err := agent.db.Get(&contentJSON, "SELECT content FROM agent_sessions WHERE session_id = ? AND user_id = ?", sessionID, userID)
	if err != nil {
		if err == sql.ErrNoRows {
			return fmt.Errorf("会话不存在或无权访问: %s", sessionID)
		}
		return fmt.Errorf("从数据库加载会话失败: %v", err)
	}

	var session AgentSession
	if err := json.Unmarshal([]byte(contentJSON), &session); err != nil {
		return fmt.Errorf("解码会话数据失败: %v", err)
	}

	agent.history = session.History
	agent.sessionID = session.ID
	return nil
}

// SaveSession 保存会话（需要传入userID）
func (agent *AIAgent) SaveSession(userID int) error {
	sessionName := "新建草稿"
	if len(agent.history) > 1 {
		for _, msg := range agent.history[1:] {
			if msg.Role == ark.ChatMessageRoleUser {
				sessionName = msg.Content
				break
			}
		}
	}

	// 确保sessionName是有效的UTF-8字符串
	sessionName = strings.ToValidUTF8(sessionName, "?")
	// 限制sessionName长度，避免数据库字段长度问题
	if len([]rune(sessionName)) > 1000 {
		sessionName = string([]rune(sessionName)[:1000])
	}

	session := ChatSession{
		ID:        agent.sessionID,
		Name:      sessionName,
		History:   agent.history,
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	sessionJSON, err := json.Marshal(session)
	if err != nil {
		return fmt.Errorf("编码会话数据失败: %v", err)
	}

	// 确保JSON数据是有效的UTF-8
	jsonStr := strings.ToValidUTF8(string(sessionJSON), "?")

	var count int
	err = agent.db.Get(&count, "SELECT COUNT(*) FROM agent_sessions WHERE session_id = ?", agent.sessionID)
	if err != nil {
		return fmt.Errorf("检查会话存在性失败: %v", err)
	}

	currentTime := helper.GetCurrentTimeString()

	if count > 0 {
		_, err = agent.db.Exec(`
			UPDATE agent_sessions 
			SET session_name = ?, content = ?, updated_at = ? 
			WHERE session_id = ?
		`, sessionName, jsonStr, currentTime, agent.sessionID)
	} else {
		_, err = agent.db.Exec(`
			INSERT INTO agent_sessions (session_id, session_name, content, user_id, created_at, updated_at) 
			VALUES (?, ?, ?, ?, ?, ?)
		`, agent.sessionID, sessionName, jsonStr, userID, currentTime, currentTime)
	}

	if err != nil {
		return fmt.Errorf("保存会话到数据库失败: %v", err)
	}

	return nil
}

// 创建新会话
func CreateAgentSession(c *gin.Context) {
	// 获取用户ID
	userIDInterface, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, AgentSessionResponse{
			Success: false,
			Error:   "未登录",
		})
		return
	}
	userID := userIDInterface.(int)

	// 创建新的聊天机器人实例
	agent := NewAIAgentWithSession(
		agent_config["content"]["gemini_flash"]["api_key"],
		agent_config["content"]["gemini_flash"]["base_url"],
		agent_config["content"]["gemini_flash"]["model"],
		"",
	)

	// 保存会话
	if err := agent.SaveSession(userID); err != nil {
		c.JSON(http.StatusInternalServerError, AgentSessionResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}

	session := AgentSession{
		ID:        agent.sessionID,
		Name:      "新建草稿",
		History:   agent.history,
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	c.JSON(http.StatusOK, AgentSessionResponse{
		Session: session,
		Success: true,
	})
}

// 获取所有会话
func GetAgentSessions(c *gin.Context) {
	// 获取用户ID
	userIDInterface, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, AgentSessionListResponse{
			Success: false,
			Error:   "未登录",
		})
		return
	}
	userID := userIDInterface.(int)

	sessions, err := ListAgentSessions(userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, AgentSessionListResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, AgentSessionListResponse{
		Sessions: sessions,
		Success:  true,
	})
}

// ListSessions 从数据库列出指定用户的所有会话
func ListAgentSessions(userID int) ([]AgentSession, error) {
	var rows []AgentSessionRow
	err := database.Db.Select(&rows, `
		SELECT session_id, session_name, content, user_id, created_at, updated_at 
		FROM agent_sessions 
		WHERE user_id = ?
		ORDER BY updated_at DESC
	`, userID)
	if err != nil {
		return nil, fmt.Errorf("查询会话列表失败: %v", err)
	}

	var sessions []AgentSession
	for _, row := range rows {
		var session AgentSession
		if err := json.Unmarshal([]byte(row.Content), &session); err != nil {
			continue
		}

		// 更新从数据库读取的时间戳
		session.CreatedAt = row.CreatedAt
		session.UpdatedAt = row.UpdatedAt
		sessions = append(sessions, session)
	}

	return sessions, nil
}

// 加载会话
func LoadAgentSession(c *gin.Context) {
	// 获取用户ID
	userIDInterface, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, AgentSessionResponse{
			Success: false,
			Error:   "未登录",
		})
		return
	}
	userID := userIDInterface.(int)

	sessionID := c.Param("id")

	agent := NewAIAgentWithSession(
		agent_config["content"]["gemini_flash"]["api_key"],
		agent_config["content"]["gemini_flash"]["base_url"],
		agent_config["content"]["gemini_flash"]["model"],
		sessionID,
	)

	if err := agent.LoadAgentSession(sessionID, userID); err != nil {
		c.JSON(http.StatusNotFound, SessionResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}

	session := AgentSession{
		ID:        agent.sessionID,
		Name:      getSessionName(agent.history),
		History:   agent.history,
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	var article GetArticleResponse
	err := database.Db.Get(&article, `
	SELECT
		COALESCE(article_content, '')  AS article_content,
		COALESCE(article_title, '')    AS article_title,
		COALESCE(article_category, '') AS article_category,
		COALESCE(article_tags, '')     AS article_tags,
		COALESCE(article_cover, '')    AS article_cover
	FROM agent_sessions
	WHERE session_id = ? AND user_id = ?`, sessionID, userID)
	if err != nil {
		c.JSON(http.StatusNotFound, AgentSessionResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}
	c.JSON(http.StatusOK, AgentSessionResponse{
		Session:         session,
		Success:         true,
		ArticleContent:  article.ArticleContent,
		ArticleTitle:    article.ArticleTitle,
		ArticleCategory: article.ArticleCategory,
		ArticleTags:     article.ArticleTags,
		ArticleCover:    article.ArticleCover,
	})
}

// 删除会话
func DeleteAgentSession(c *gin.Context) {
	// 获取用户ID
	userIDInterface, exists := c.Get("userId")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"success": false,
			"error":   "未登录",
		})
		return
	}
	userID := userIDInterface.(int)

	sessionID := c.Param("id")

	if err := deleteAgentSession(sessionID, userID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"success": false,
			"error":   err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "会话删除成功",
	})
}

// DeleteSession 从数据库删除会话（需要传入userID进行权限验证）
func deleteAgentSession(sessionID string, userID int) error {
	result, err := database.Db.Exec("DELETE FROM agent_sessions WHERE session_id = ? AND user_id = ?", sessionID, userID)
	if err != nil {
		return fmt.Errorf("删除会话失败: %v", err)
	}

	rowsAffected, err := result.RowsAffected()
	if err != nil {
		return fmt.Errorf("获取删除结果失败: %v", err)
	}

	if rowsAffected == 0 {
		return fmt.Errorf("会话不存在或无权删除: %s", sessionID)
	}

	return nil
}

func SaveArticle(c *gin.Context) {
	var req SaveArticleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"success": false,
			"error":   err.Error(),
		})
		return
	}
	
	loc, _ := time.LoadLocation("Asia/Shanghai")
	currentTime := time.Now().In(loc)
	
	err := models.Db.Model(&AgentSessionModel{}).
		Where("session_id = ?", req.SessionID).
		Updates(map[string]interface{}{
			"article_content":  req.ArticleContent,
			"article_title":    req.ArticleTitle,
			"article_category": req.ArticleCategory,
			"article_tags":     req.ArticleTags,
			"article_cover":    req.ArticleCover,
			"updated_at":       currentTime,
		}).Error
		
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"success": false,
			"error":   err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "文章保存成功",
	})
}

func GetArticle(c *gin.Context) {
	sessionID := c.Param("id")
	var article GetArticleResponse
	err := database.Db.Get(&article, `
	SELECT
		COALESCE(article_content, '')  AS article_content,
		COALESCE(article_title, '')    AS article_title,
		COALESCE(article_category, '') AS article_category,
		COALESCE(article_tags, '')     AS article_tags,
		COALESCE(article_cover, '')    AS article_cover
	FROM agent_sessions
	WHERE session_id = ?`, sessionID)
	if err != nil {
		c.JSON(http.StatusNotFound, GetArticleResponse{
			Success: false,
			Error:   err.Error(),
		})
		return
	}
	c.JSON(http.StatusOK, GetArticleResponse{
		Success:         true,
		ArticleContent:  article.ArticleContent,
		ArticleTitle:    article.ArticleTitle,
		ArticleCategory: article.ArticleCategory,
		ArticleTags:     article.ArticleTags,
		ArticleCover:    article.ArticleCover,
	})
}

func GetAllAgentModel(c *gin.Context) {
	models := agent_config["content"]
	modelsMap := []map[string]string{}
	for model, modelInfo := range models {
		modelsMap = append(modelsMap, map[string]string{
			"model":      model,
			"model_name": modelInfo["model_name"],
			"icon_url":   modelInfo["icon_url"],
		})
	}
	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"models":  modelsMap,
	})
}

// UpdateResult 更新结果
type UpdateResult struct {
	Success     bool   `json:"success"`
	UpdatedText string `json:"updated_text"`
	Message     string `json:"message"`
}
